package com.example.businessmanage.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.api.client.UserClient;
import com.example.businessmanage.domain.dto.*;
import com.example.businessmanage.domain.po.FosterAgreementPO;
import com.example.businessmanage.domain.po.FosterBusinessPO;
import com.example.businessmanage.domain.po.FosterIntentPO;
import com.example.api.client.PetInfoFeignClient;
import com.example.businessmanage.mapper.FosterAgreementMapper;
import com.example.businessmanage.mapper.FosterBusinessMapper;
import com.example.businessmanage.mapper.FosterIntentMapper;
import com.example.businessmanage.service.FosterService;
import com.example.api.dto.PetInfoRespDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 代养业务实现类
 */
@Service
@RequiredArgsConstructor
public class FosterServiceImpl implements FosterService {

    private final PetInfoFeignClient petInfoFeignClient;
    private final UserClient userFeignClient;
    private final FosterIntentMapper fosterIntentMapper;
    private final FosterAgreementMapper fosterAgreementMapper;
    private final FosterBusinessMapper fosterBusinessMapper;

    /**
     * 脱敏手机号（如138****1234）
     */
    private String desensitizePhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }

    /**
     * 数字外借状态转文本描述（与pet-info-service一致）
     */
    private String getLendStatusDesc(Integer status) {
        switch (status) {
            case 0: return "不外借";
            case 1: return "已申请外借";
            case 2: return "已选择代养";
            case 3: return "运输中";
            case 4: return "在代养人手里";
            case 5: return "主人申请返回";
            case 6: return "代养人申请返回";
            case 7: return "返回中";
            default: return "未知状态";
        }
    }

    /**
     * 代养业务状态转文本描述
     */
    private String getBusinessStatusDesc(Integer status) {
        switch (status) {
            case 1: return "待确认代养";
            case 2: return "运输中";
            case 3: return "代养中";
            case 4: return "待返回";
            case 5: return "已完成";
            default: return "未知业务状态";
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean sendFosterIntent(FosterIntentDTO fosterIntentDTO, Long fosterUserId) {
        // 1. 校验参数
        Long petId = fosterIntentDTO.getPetId();
        Assert.notNull(petId, "宠物ID不能为空");
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");

        // 2. 校验宠物状态（必须是1-已申请外借或6-代养人申请返回）
        PetInfoRespDTO petInfo = petInfoFeignClient.getPetInfoById(petId);
        Assert.notNull(petInfo, "宠物不存在");
        String currentStatus = petInfo.getLendStatusDesc();
        Assert.isTrue(currentStatus.equals("已申请外借") || currentStatus.equals("代养人申请返回"),
                "当前宠物状态不支持发送代养意向（需为“已申请外借”或“代养人申请返回”）");

        // 3. 校验是否已发送过意向（避免重复发送）
        FosterIntentPO existIntent = fosterIntentMapper.selectByFosterAndPet(fosterUserId, petId);
        Assert.isNull(existIntent, "已向该宠物发送过代养意向，无需重复操作");

        // 4. 新增代养意向记录
        FosterIntentPO intentPO = new FosterIntentPO();
        intentPO.setPetId(petId);
        intentPO.setFosterUserId(fosterUserId);
        fosterIntentMapper.insert(intentPO);

        // 5. 同步更新pet_info的“待选择代养人集合”（查询该宠物所有代养人ID，用逗号拼接）
        List<Long> fosterIds = fosterIntentMapper.selectFosterIdsByPetId(petId);
        String fosterIdsStr = StringUtils.collectionToCommaDelimitedString(fosterIds);
        return petInfoFeignClient.updateToBeSelectedFosterIds(petId, fosterIdsStr);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmFoster(FosterConfirmDTO fosterConfirmDTO, Long fosterUserId) {
        // 1. 校验参数
        Long petId = fosterConfirmDTO.getPetId();
        Boolean confirmResult = fosterConfirmDTO.getConfirmResult();
        Assert.notNull(petId, "宠物ID不能为空");
        Assert.notNull(confirmResult, "处理结果不能为空");
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");

        // 2. 校验宠物状态（必须是2-已选择代养，且负责人是当前代养人）
        PetInfoRespDTO petInfo = petInfoFeignClient.getPetInfoById(petId);
        Assert.notNull(petInfo, "宠物不存在");
        Assert.isTrue(petInfo.getLendStatusDesc().equals("已选择代养"), "当前宠物状态不支持确认代养（需为“已选择代养”）");
        Assert.isTrue(fosterUserId.equals(petInfo.getResponsibleUserId()), "无权限处理该宠物的代养确认");

        // 3. 确认代养：需校验协议已上传，更新状态为3-运输中，同时初始化代养业务记录
        if (confirmResult) {
            Long agreementId = fosterConfirmDTO.getAgreementId();
            Assert.notNull(agreementId, "确认代养需关联已上传的协议");

            // 3.1 校验协议归属（协议必须是当前代养人针对该宠物签署的）
            FosterAgreementPO agreementPO = fosterAgreementMapper.selectById(agreementId);
            Assert.notNull(agreementPO, "协议不存在");
            Assert.isTrue(agreementPO.getPetId().equals(petId) && agreementPO.getFosterUserId().equals(fosterUserId),
                    "协议与当前宠物/代养人不匹配");

            // 3.2 远程更新宠物外借状态（2→3-运输中）
            Boolean statusUpdate = petInfoFeignClient.updateLendStatus(petId, 3, fosterUserId);
            if (!statusUpdate) {
                return false;
            }

            // 3.3 初始化代养业务记录（状态1→2-运输中）
            FosterBusinessPO businessPO = fosterBusinessMapper.selectByPetAndFoster(petId, fosterUserId, 5);
            if (businessPO == null) {
                businessPO = new FosterBusinessPO();
                businessPO.setPetId(petId);
                businessPO.setOwnerUserId(petInfo.getOwnerUserId());
                businessPO.setFosterUserId(fosterUserId);
                businessPO.setBusinessStatus(2); // 运输中
                fosterBusinessMapper.insert(businessPO);
            } else {
                businessPO.setBusinessStatus(2);
                fosterBusinessMapper.updateById(businessPO);
            }

        } else {
            // 4. 拒绝代养：更新宠物状态为1-已申请外借
            Boolean statusUpdate = petInfoFeignClient.updateLendStatus(petId, 1, petInfo.getOwnerUserId());
            if (!statusUpdate) {
                return false;
            }

            // 4.1 （可选）删除该代养人的意向记录（避免再次被选择）
            fosterIntentMapper.deleteById(fosterIntentMapper.selectByFosterAndPet(fosterUserId, petId).getId());
            // 4.2 重新同步pet_info的“待选择代养人集合”
            List<Long> fosterIds = fosterIntentMapper.selectFosterIdsByPetId(petId);
            String fosterIdsStr = StringUtils.collectionToCommaDelimitedString(fosterIds);
            petInfoFeignClient.updateToBeSelectedFosterIds(petId, fosterIdsStr);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean confirmReceivePet(Long petId, Long fosterUserId) {
        // 1. 校验参数
        Assert.notNull(petId, "宠物ID不能为空");
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");

        // 2. 校验宠物状态（必须是3-运输中，且负责人是当前代养人）
        PetInfoRespDTO petInfo = petInfoFeignClient.getPetInfoById(petId);
        Assert.notNull(petInfo, "宠物不存在");
        Assert.isTrue(petInfo.getLendStatusDesc().equals("运输中"), "当前宠物状态不支持确认接收（需为“运输中”）");
        Assert.isTrue(fosterUserId.equals(petInfo.getResponsibleUserId()), "无权限确认接收该宠物");

        // 3. 远程更新宠物外借状态（3→4-在代养人手里）
        Boolean statusUpdate = petInfoFeignClient.updateLendStatus(petId, 4, fosterUserId);
        if (!statusUpdate) {
            return false;
        }

        // 4. 同步更新代养业务状态（2-运输中→3-代养中）
        fosterBusinessMapper.updateBusinessStatusByPetId(petId, 3);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean applyReturnPet(Long petId, Long fosterUserId) {
        // 1. 校验参数
        Assert.notNull(petId, "宠物ID不能为空");
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");

        // 2. 校验宠物状态（必须是4-在代养人手里或5-主人申请返回，且负责人是当前代养人）
        PetInfoRespDTO petInfo = petInfoFeignClient.getPetInfoById(petId);
        Assert.notNull(petInfo, "宠物不存在");
        Assert.isTrue(fosterUserId.equals(petInfo.getResponsibleUserId()), "无权限申请返回该宠物");
        String currentStatus = petInfo.getLendStatusDesc();
        Integer targetStatus;

        // 3. 根据当前状态确定目标状态
        if (currentStatus.equals("在代养人手里")) {
            // 4→6-代养人申请返回
            targetStatus = 6;
        } else if (currentStatus.equals("主人申请返回")) {
            // 5→7-返回中
            targetStatus = 7;
        } else {
            throw new IllegalArgumentException("当前状态（" + currentStatus + "）不支持申请返回");
        }

        // 4. 远程更新宠物外借状态
        Boolean statusUpdate = petInfoFeignClient.updateLendStatus(petId, targetStatus, fosterUserId);
        if (!statusUpdate) {
            return false;
        }

        // 5. 同步更新代养业务状态（3-代养中→4-待返回）
        if (targetStatus == 6) {
            fosterBusinessMapper.updateBusinessStatusByPetId(petId, 4);
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean uploadAgreement(AgreementUploadDTO agreementUploadDTO, Long fosterUserId) {
        // 1. 校验参数
        Long petId = agreementUploadDTO.getPetId();
        String agreementUrl = agreementUploadDTO.getAgreementUrl();
        Assert.notNull(petId, "宠物ID不能为空");
        Assert.hasText(agreementUrl, "协议OSS URL不能为空");
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");

        // 2. 校验宠物状态（必须是1-已申请外借或2-已选择代养，避免无效协议上传）
        PetInfoRespDTO petInfo = petInfoFeignClient.getPetInfoById(petId);
        Assert.notNull(petInfo, "宠物不存在");
        String currentStatus = petInfo.getLendStatusDesc();
        Assert.isTrue(currentStatus.equals("已申请外借") || currentStatus.equals("已选择代养"),
                "当前宠物状态不支持上传协议（需为“已申请外借”或“已选择代养”）");

        // 3. 校验是否已上传协议（避免重复上传）
        FosterAgreementPO existAgreement = fosterAgreementMapper.selectByFosterAndPet(fosterUserId, petId);
        Assert.isNull(existAgreement, "已为该宠物上传过代养协议，无需重复操作");

        // 4. 新增协议记录
        FosterAgreementPO agreementPO = new FosterAgreementPO();
        agreementPO.setPetId(petId);
        agreementPO.setFosterUserId(fosterUserId);
        agreementPO.setAgreementUrl(agreementUrl);
        fosterAgreementMapper.insert(agreementPO);
        return true;
    }

    @Override
    public IPage<FosterBusinessRespDTO> getMyFoster(Long fosterUserId, Integer pageNum, Integer pageSize) {
        // 1. 校验参数
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");
        Assert.notNull(pageNum, "页码不能为空");
        Assert.notNull(pageSize, "每页条数不能为空");

        // 2. 分页查询“我的代养”业务记录（状态≥2-已选择代养，排除已完成）
        Page<FosterBusinessPO> page = new Page<>(pageNum, pageSize);
        IPage<FosterBusinessPO> businessPage = fosterBusinessMapper.selectMyFosterPage(page, fosterUserId, 2);
        if (CollectionUtils.isEmpty(businessPage.getRecords())) {
            return new Page<>();
        }

        // 3. 批量获取关联数据：宠物信息（品种）、主人信息（昵称、联系方式）
        // 3.1 批量获取宠物ID→品种映射
        List<Long> petIds = businessPage.getRecords().stream()
                .map(FosterBusinessPO::getPetId)
                .distinct()
                .collect(Collectors.toList());
        Map<Long, String> petBreedMap = petIds.stream()
                .collect(Collectors.toMap(
                        petId -> petId,
                        petId -> petInfoFeignClient.getPetInfoById(petId).getPetBreed()
                ));

        // 3.2 批量获取主人ID→基础信息映射
        List<Long> ownerIds = businessPage.getRecords().stream()
                .map(FosterBusinessPO::getOwnerUserId)
                .distinct()
                .collect(Collectors.toList());
        String ownerIdsStr = StringUtils.collectionToCommaDelimitedString(ownerIds);
        Map<Long, Map<String, String>> ownerInfoMap = userFeignClient.batchGetUserBasicInfo(ownerIdsStr);

        // 4. 转换为DTO分页结果
        return businessPage.convert(businessPO -> {
            Long petId = businessPO.getPetId();
            Long ownerUserId = businessPO.getOwnerUserId();
            Map<String, String> ownerInfo = ownerInfoMap.getOrDefault(ownerUserId, Map.of());

            FosterBusinessRespDTO dto = new FosterBusinessRespDTO();
            dto.setBusinessId(businessPO.getId());
            dto.setPetId(petId);
            dto.setPetBreed(petBreedMap.getOrDefault(petId, "未知品种"));
            dto.setOwnerUserId(ownerUserId);
//            dto.setOwnerUserName(ownerInfo.getOrDefault("userName", "未知主人"));
            dto.setOwnerPhone(desensitizePhone(ownerInfo.getOrDefault("phone", "")));
            dto.setBusinessStatusDesc(getBusinessStatusDesc(businessPO.getBusinessStatus()));
            dto.setCreateTime(businessPO.getCreateTime());
            dto.setUpdateTime(businessPO.getUpdateTime());
            return dto;
        });
    }

    @Override
    public IPage<PetSimpleRespDTO> getToBeSelectedPet(Long fosterUserId, Integer pageNum, Integer pageSize) {
        // 1. 校验参数
        Assert.notNull(fosterUserId, "代养人用户ID不能为空");
        Assert.notNull(pageNum, "页码不能为空");
        Assert.notNull(pageSize, "每页条数不能为空");

        // 2. 分页查询“待选择代养宠物”意向记录（代养人已发送意向的宠物）
        Page<FosterIntentPO> page = new Page<>(pageNum, pageSize);
        IPage<FosterIntentPO> intentPage = fosterIntentMapper.selectPetByFosterId(page, fosterUserId);
        if (CollectionUtils.isEmpty(intentPage.getRecords())) {
            return new Page<>(); // 无数据时返回空分页
        }

        // 3. 批量获取关联数据：宠物基础信息、主人昵称
        // 3.1 提取所有宠物ID，批量查询宠物信息（避免循环调用Feign）
        List<Long> petIds = intentPage.getRecords().stream()
                .map(FosterIntentPO::getPetId)
                .distinct()
                .collect(Collectors.toList());
        // 构建“宠物ID→宠物信息”映射（减少Feign调用次数）
        Map<Long, PetInfoRespDTO> petInfoMap = petIds.stream()
                .collect(Collectors.toMap(
                        petId -> petId,
                        petId -> petInfoFeignClient.getPetInfoById(petId)
                ));

        // 3.2 提取所有主人ID，批量查询主人昵称（脱敏展示）
        List<Long> ownerIds = petInfoMap.values().stream()
                .map(PetInfoRespDTO::getOwnerUserId)
                .distinct()
                .collect(Collectors.toList());
        String ownerIdsStr = StringUtils.collectionToCommaDelimitedString(ownerIds);
        Map<Long, Map<String, String>> ownerInfoMap = userFeignClient.batchGetUserBasicInfo(ownerIdsStr);

        // 4. 转换为“宠物简易信息DTO”，封装分页结果
        return intentPage.convert(intentPO -> {
            Long petId = intentPO.getPetId();
            PetInfoRespDTO petInfo = petInfoMap.get(petId);
            Long ownerUserId = petInfo.getOwnerUserId();
            Map<String, String> ownerInfo = ownerInfoMap.getOrDefault(ownerUserId, Map.of());

            PetSimpleRespDTO dto = new PetSimpleRespDTO();
            dto.setPetId(petId);
            dto.setPetBreed(petInfo.getPetBreed()); // 宠物品种（如“布偶猫”）
            dto.setPetCategory(petInfo.getPetCategory()); // 宠物分类（如“猫类”）
            // 健康状况简化展示（为空时显示“未填写”）
            dto.setHealthStatus(StringUtils.hasText(petInfo.getHealthStatus())
                    ? petInfo.getHealthStatus()
                    : "未填写");
            // 主人昵称脱敏（如“张**”）
            String ownerName = ownerInfo.getOrDefault("userName", "未知主人");
            dto.setOwnerUserName(desensitizeUserName(ownerName));
            // 意向发送时间格式化（如“2024-05-20 14:30”）
            dto.setIntentCreateTime(intentPO.getCreateTime()
                    .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
            return dto;
        });
    }

    /**
     * 脱敏用户名（2字及以上显示首字+*，1字显示原字）
     * 例：张三→张*，李→李，王小明→王**
     */
    private String desensitizeUserName(String userName) {
        if (userName == null || userName.length() <= 1) {
            return userName;
        }
        return userName.substring(0, 1) + "*".repeat(userName.length() - 1);
    }
}
